//
// Created by RandBII on 2020/12/25.
//

#include "AudioDecoder.h"

AudioDecoder::AudioDecoder(char *url) {
    Init(url, AVMEDIA_TYPE_AUDIO);
}

AudioDecoder::~AudioDecoder() {
    UnInit();
}

void AudioDecoder::SetAudioRender(AudioRender *render) {
    this->m_AudioRender = render;
}

void AudioDecoder::OnDecoderReady() {

    if (m_AudioRender) {
        AVCodecContext *codecCtx = GetCodecContext();
        m_SwrContext = swr_alloc();
//        根据 参数名 设置参数值
        av_opt_set_int(m_SwrContext, "in_channel_layout", codecCtx->channel_layout, 0);
        av_opt_set_int(m_SwrContext, "out_channel_layout", AUDIO_DST_CHANNEL_LAYOUT, 0);

        av_opt_set_int(m_SwrContext, "in_sample_rate", codecCtx->sample_rate, 0);
        av_opt_set_int(m_SwrContext, "out_sample_rate", AUDIO_DST_SAMPLE_RATE, 0);

        av_opt_set_sample_fmt(m_SwrContext, "in_sample_fmt", codecCtx->sample_fmt, 0);
        av_opt_set_sample_fmt(m_SwrContext, "out_sample_fmt", DST_SAMPLE_FORMAT, 0);
        //参数设置完之后，初始化环境
        swr_init(m_SwrContext);
        // 采用四舍五入， 重新缩放64位整数
        m_nbSample = av_rescale_rnd(ACC_SAMPLE_RATE, AUDIO_DST_SAMPLE_RATE,
                                    codecCtx->sample_rate, AV_ROUND_UP);

        m_DstFrameSize = av_samples_get_buffer_size(NULL, AUDIO_DST_CHANNEL_COUNTS,
                                                    m_nbSample, DST_SAMPLE_FORMAT, 1);
        m_AudioOutBuffer = static_cast<uint8_t *>(malloc(m_DstFrameSize));
        m_AudioRender->Init();
    }
}

void AudioDecoder::OnDecoderDone() {
    if (m_AudioRender) m_AudioRender->UnInit();
    if (m_AudioOutBuffer) {
        free(m_AudioOutBuffer);
        m_AudioOutBuffer = nullptr;
    }
    if (m_SwrContext) {
        swr_free(&m_SwrContext);
        m_SwrContext = nullptr;
    }


}

void AudioDecoder::OnFrameAvailable(AVFrame *frame) {

    if (m_AudioRender) {
        int result = swr_convert(m_SwrContext, &m_AudioOutBuffer, m_DstFrameSize / 2,
                                 (const uint8_t **) frame->data, frame->nb_samples);
        if (result > 0) m_AudioRender->RenderAudioFrame(m_AudioOutBuffer, m_DstFrameSize);
    }

}

void AudioDecoder::ClearCache() {
    DecoderBase::ClearCache();
    if (m_AudioRender) m_AudioRender->ClearAudioCache();
}

long AudioDecoder::GetAudioDecoderTimestampForAVSync(void *context) {
    if (context) {
        auto *audioDecoder = static_cast<AudioDecoder *>(context);
        return audioDecoder->GetCurrentPosition();
    }
    return 0;
}

float AudioDecoder::GetCurrentPosition() {
    return 0;
}
